﻿
// MachineScheduleDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "MachineSchedule.h"
#include "MachineScheduleDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMachineScheduleDlg 对话框

CMachineScheduleDlg::CMachineScheduleDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_MACHINESCHEDULE_DIALOG, pParent)
	, mCount(0)
	, jCount(0)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMachineScheduleDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_M_COUNT, mCount);
	DDV_MinMaxInt(pDX, mCount, 0, 10);
	DDX_Text(pDX, IDC_J_COUNT, jCount);
	DDV_MinMaxInt(pDX, jCount, 0, 10);
}

BEGIN_MESSAGE_MAP(CMachineScheduleDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_M_ADD, &CMachineScheduleDlg::OnBnClickedMAdd)
	ON_BN_CLICKED(IDC_M_DEL, &CMachineScheduleDlg::OnBnClickedMDel)
	ON_BN_CLICKED(IDC_J_ADD, &CMachineScheduleDlg::OnBnClickedJAdd)
	ON_BN_CLICKED(IDC_J_DEL, &CMachineScheduleDlg::OnBnClickedJDel)
	ON_BN_CLICKED(IDC_START, &CMachineScheduleDlg::OnBnClickedStart)
	ON_BN_CLICKED(IDC_RESET, &CMachineScheduleDlg::OnBnClickedReset)
	ON_BN_CLICKED(IDC_SLOW, &CMachineScheduleDlg::OnBnClickedSlow)
	ON_BN_CLICKED(IDC_FAST, &CMachineScheduleDlg::OnBnClickedFast)
	ON_BN_CLICKED(IDC_FASTEST, &CMachineScheduleDlg::OnBnClickedFastest)
	ON_WM_CTLCOLOR()
END_MESSAGE_MAP()


//增加机器
void CMachineScheduleDlg::addMachine(int id) {
	//更新机器状态
	switch (id) {
	case 1:
		SetDlgItemText(IDC_M_PLACE1, "机器1");
		break;
	case 2:
		SetDlgItemText(IDC_M_PLACE2, "机器2");
		break;
	case 3:
		SetDlgItemText(IDC_M_PLACE3, "机器3");
		break;
	case 4:
		SetDlgItemText(IDC_M_PLACE4, "机器4");
		break;
	case 5:
		SetDlgItemText(IDC_M_PLACE5, "机器5");
		break;
	case 6:
		SetDlgItemText(IDC_M_PLACE6, "机器6");
		break;
	case 7:
		SetDlgItemText(IDC_M_PLACE7, "机器7");
		break;
	case 8:
		SetDlgItemText(IDC_M_PLACE8, "机器8");
		break;
	case 9:
		SetDlgItemText(IDC_M_PLACE9, "机器9");
		break;
	case 10:
		SetDlgItemText(IDC_M_PLACE10, "机器10");
		break;
	}
}

//移除机器
void CMachineScheduleDlg::delMachine(int id) {
	//更新机器状态
	switch (id) {
	case 1:
		SetDlgItemText(IDC_M_PLACE1, "机器位");
		SetDlgItemText(IDC_M_STATUS1, "");
		break;
	case 2:
		SetDlgItemText(IDC_M_PLACE2, "机器位");
		SetDlgItemText(IDC_M_STATUS2, "");
		break;
	case 3:
		SetDlgItemText(IDC_M_PLACE3, "机器位");
		SetDlgItemText(IDC_M_STATUS3, "");
		break;
	case 4:
		SetDlgItemText(IDC_M_PLACE4, "机器位");
		SetDlgItemText(IDC_M_STATUS4, "");
		break;
	case 5:
		SetDlgItemText(IDC_M_PLACE5, "机器位");
		SetDlgItemText(IDC_M_STATUS5, "");
		break;
	case 6:
		SetDlgItemText(IDC_M_PLACE6, "机器位");
		SetDlgItemText(IDC_M_STATUS6, "");
		break;
	case 7:
		SetDlgItemText(IDC_M_PLACE7, "机器位");
		SetDlgItemText(IDC_M_STATUS7, "");
		break;
	case 8:
		SetDlgItemText(IDC_M_PLACE8, "机器位");
		SetDlgItemText(IDC_M_STATUS8, "");
		break;
	case 9:
		SetDlgItemText(IDC_M_PLACE9, "机器位");
		SetDlgItemText(IDC_M_STATUS9, "");
		break;
	case 10:
		SetDlgItemText(IDC_M_PLACE10, "机器位");
		SetDlgItemText(IDC_M_STATUS10, "");
		break;
	}
}

//增加作业
void CMachineScheduleDlg::addJob(int id) {
	CString ID;
	CString time;
	CString jobName;
	ID.Format(_T("%d"), id);
	time.Format(_T("%d"), jobs[id - 1].time);
	jobName = "作业" + ID + "(" + time + ")";

	//更新作业状态
	switch (id) {
	case 1:
		SetDlgItemText(IDC_J_PLACE1,jobName);
		break;
	case 2:
		SetDlgItemText(IDC_J_PLACE2, jobName);
		break;
	case 3:
		SetDlgItemText(IDC_J_PLACE3, jobName);
		break;
	case 4:
		SetDlgItemText(IDC_J_PLACE4, jobName);
		break;
	case 5:
		SetDlgItemText(IDC_J_PLACE5, jobName);
		break;
	case 6:
		SetDlgItemText(IDC_J_PLACE6, jobName);
		break;
	case 7:
		SetDlgItemText(IDC_J_PLACE7, jobName);
		break;
	case 8:
		SetDlgItemText(IDC_J_PLACE8, jobName);
		break;
	case 9:
		SetDlgItemText(IDC_J_PLACE9, jobName);
		break;
	case 10:
		SetDlgItemText(IDC_J_PLACE10, jobName);
		break;
	}
	setJobStatus(id);
}

//移除作业
void CMachineScheduleDlg::delJob(int id) {
	//更新作业状态
	switch (id) {
	case 1:
		SetDlgItemText(IDC_J_PLACE1, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS1))->SetBitmap(hbmpGray);
		break;
	case 2:
		SetDlgItemText(IDC_J_PLACE2, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS2))->SetBitmap(hbmpGray);
		break;
	case 3:
		SetDlgItemText(IDC_J_PLACE3, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS3))->SetBitmap(hbmpGray);
		break;
	case 4:
		SetDlgItemText(IDC_J_PLACE4, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS4))->SetBitmap(hbmpGray);
		break;
	case 5:
		SetDlgItemText(IDC_J_PLACE5, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS5))->SetBitmap(hbmpGray);
		break;
	case 6:
		SetDlgItemText(IDC_J_PLACE6, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS6))->SetBitmap(hbmpGray);
		break;
	case 7:
		SetDlgItemText(IDC_J_PLACE7, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS7))->SetBitmap(hbmpGray);
		break;
	case 8:
		SetDlgItemText(IDC_J_PLACE8, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS8))->SetBitmap(hbmpGray);
		break;
	case 9:
		SetDlgItemText(IDC_J_PLACE9, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS9))->SetBitmap(hbmpGray);
		break;
	case 10:
		SetDlgItemText(IDC_J_PLACE10, "作业位");
		((CStatic*)GetDlgItem(IDC_J_STATUS10))->SetBitmap(hbmpGray);
		break;
	}
}

//处理作业
void CMachineScheduleDlg::doJob(int mID,int jID,bool done) {
	CString status;
	HBITMAP hbmp;

	//若作业状态为“完成”，则机器状态变为“空闲”
	//作业状态指示灯变为绿色
	//否则处理作业
	if (done) {
		status = "空闲";
		hbmp = hbmpGreen;
	}
	else {
		CString job;
		job.Format(_T("%d"), jID);
		status = "处理作业" + job;
		hbmp = hbmpRed;
	}

	//更新机器状态
	switch (mID) {
	case 1:
		SetDlgItemText(IDC_M_STATUS1,status);
		break;
	case 2:
		SetDlgItemText(IDC_M_STATUS2, status);
		break;
	case 3:
		SetDlgItemText(IDC_M_STATUS3, status);
		break;
	case 4:
		SetDlgItemText(IDC_M_STATUS4, status);
		break;
	case 5:
		SetDlgItemText(IDC_M_STATUS5, status);
		break;
	case 6:
		SetDlgItemText(IDC_M_STATUS6, status);
		break;
	case 7:
		SetDlgItemText(IDC_M_STATUS7, status);
		break;
	case 8:
		SetDlgItemText(IDC_M_STATUS8, status);
		break;
	case 9:
		SetDlgItemText(IDC_M_STATUS9, status);
		break;
	case 10:
		SetDlgItemText(IDC_M_STATUS10, status);
		break;
	}

	//更新作业状态
	switch (jID) {
	case 1:
		((CStatic*)GetDlgItem(IDC_J_STATUS1))->SetBitmap(hbmp);
		break;
	case 2:
		((CStatic*)GetDlgItem(IDC_J_STATUS2))->SetBitmap(hbmp);
		break;
	case 3:
		((CStatic*)GetDlgItem(IDC_J_STATUS3))->SetBitmap(hbmp);
		break;
	case 4:
		((CStatic*)GetDlgItem(IDC_J_STATUS4))->SetBitmap(hbmp);
		break;
	case 5:
		((CStatic*)GetDlgItem(IDC_J_STATUS5))->SetBitmap(hbmp);
		break;
	case 6:
		((CStatic*)GetDlgItem(IDC_J_STATUS6))->SetBitmap(hbmp);
		break;
	case 7:
		((CStatic*)GetDlgItem(IDC_J_STATUS7))->SetBitmap(hbmp);
		break;
	case 8:
		((CStatic*)GetDlgItem(IDC_J_STATUS8))->SetBitmap(hbmp);
		break;
	case 9:
		((CStatic*)GetDlgItem(IDC_J_STATUS9))->SetBitmap(hbmp);
		break;
	case 10:
		((CStatic*)GetDlgItem(IDC_J_STATUS10))->SetBitmap(hbmp);
		break;
	}
}

//设置作业状态指示灯颜色
void CMachineScheduleDlg::setJobStatus(int id)
{
	switch (id) {
	case 1:
		((CStatic*)GetDlgItem(IDC_J_STATUS1))->SetBitmap(hbmpBlue);
		break;
	case 2:
		((CStatic*)GetDlgItem(IDC_J_STATUS2))->SetBitmap(hbmpBlue);
		break;
	case 3:
		((CStatic*)GetDlgItem(IDC_J_STATUS3))->SetBitmap(hbmpBlue);
		break;
	case 4:
		((CStatic*)GetDlgItem(IDC_J_STATUS4))->SetBitmap(hbmpBlue);
		break;
	case 5:
		((CStatic*)GetDlgItem(IDC_J_STATUS5))->SetBitmap(hbmpBlue);
		break;
	case 6:
		((CStatic*)GetDlgItem(IDC_J_STATUS6))->SetBitmap(hbmpBlue);
		break;
	case 7:
		((CStatic*)GetDlgItem(IDC_J_STATUS7))->SetBitmap(hbmpBlue);
		break;
	case 8:
		((CStatic*)GetDlgItem(IDC_J_STATUS8))->SetBitmap(hbmpBlue);
		break;
	case 9:
		((CStatic*)GetDlgItem(IDC_J_STATUS9))->SetBitmap(hbmpBlue);
		break;
	case 10:
		((CStatic*)GetDlgItem(IDC_J_STATUS10))->SetBitmap(hbmpBlue);
		break;
	}
}


// CMachineScheduleDlg 消息处理程序

BOOL CMachineScheduleDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	SetWindowLong(m_hWnd, GWL_STYLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); //固定窗口大小
	((CButton*)GetDlgItem(IDC_SLOW))->SetCheck(TRUE);	//设置调速单选按钮默认选中

	//加载位图
	bitmapRed.LoadBitmap(IDB_BITMAP_RED); 
	bitmapGreen.LoadBitmap(IDB_BITMAP_GREEN);
	bitmapGray.LoadBitmap(IDB_BITMAP_GRAY);
	bitmapBlue.LoadBitmap(IDB_BITMAP_BLUE);

	// 获取bitmap位图句柄
	hbmpRed = (HBITMAP)bitmapRed.GetSafeHandle();
	hbmpGreen = (HBITMAP)bitmapGreen.GetSafeHandle();
	hbmpGray= (HBITMAP)bitmapGray.GetSafeHandle();
	hbmpBlue = (HBITMAP)bitmapBlue.GetSafeHandle();

	//初始化画刷
	brush_M.CreateSolidBrush(RGB(0, 0, 255));

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

void CMachineScheduleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CMachineScheduleDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMachineScheduleDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

HBRUSH CMachineScheduleDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何特性
	
	//设置机器名字体颜色
	switch (pWnd->GetDlgCtrlID())
	{
	case IDC_M_PLACE1:
		if (mCount >= 1)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE2:
		if (mCount >= 2)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE3:
		if (mCount >= 3)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE4:
		if (mCount >= 4)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE5:
		if (mCount >= 5)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE6:
		if (mCount >= 6)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE7:
		if (mCount >= 7)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE8:
		if (mCount >= 8)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE9:
		if (mCount >= 9)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	case IDC_M_PLACE10:
		if (mCount >= 10)
		{
			pDC->SetTextColor(RGB(0, 0, 255));
		}
		else
		{
			pDC->SetTextColor(RGB(0, 0, 0));
		}
		break;
	}

	// TODO:  如果默认的不是所需画笔，则返回另一个画笔
	return hbr;
}

//时间响应函数
void CMachineScheduleDlg::OnTimer(UINT_PTR nIDEvent) {
	switch (nIDEvent) { //nIDEvent 为定时器事件ID，1，2，3
	case 1: {
		//机器将被占用的时间随时间递减
		for (int i = 0; i < mCount; i++) {
			if (machines[i].takenTime > 0) {
				machines[i].takenTime--;
				if (machines[i].takenTime == 0) {
					doJob(i + 1,machines[i].jobID,1);	//完成作业后机器状态变为“空闲”
					machines[i].jobID = 0;	//重置机器处理的作业
					idleCount++;	//空闲机器数加 1
				}
			}
		}

		//若作业堆为空且没有正在工作的机器，则任务完成
		finished = jobHeap.empty();
		for (int i = 0; i < mCount; i++) {
			if (machines[i].takenTime > 0) {
				finished = false;
			}
		}

		//任务完成后弹出提示信息并重置部分数据
		if (finished) {
			KillTimer(1);	//销毁计时器
			CString time;
			time.Format(_T("%d"),shortestTime);
			CString result;
			result = "作业已完成，用时 " + time + " s";
			MessageBox(result, "机器调度系统");

			//重置机器可用时刻
			for (int i = 0; i < mCount; i++) 
			{
				machines[i].avail = 0;
			}

			//清空作业处理时间输入框
			SetDlgItemText(IDC_J_TIME, "");

			//重置作业状态指示灯颜色
			for (int i = 0; i < jCount; i++)
			{
				setJobStatus(i + 1);
			}

			//重置大根堆、小根堆
			machineHeap.reset();
			jobHeap.reset();

			//任务完成时启用调速单选按钮
			((CButton*)GetDlgItem(IDC_SLOW))->EnableWindow(TRUE);
			((CButton*)GetDlgItem(IDC_FAST))->EnableWindow(TRUE);
			((CButton*)GetDlgItem(IDC_FASTEST))->EnableWindow(TRUE);
		}
		//若机器数小于作业数且作业堆不为空，则将堆顶作业分配给堆顶机器
		//将堆顶机器的可用时刻加上堆顶作业的处理时间后重新插入机器堆中
		if (mCount < jCount&&!jobHeap.empty()) {
			while (idleCount>=1&&!jobHeap.empty()) {
				int id = machineHeap.top().ID;
				machines[id - 1].jobID = jobHeap.top().ID;	//分配作业
				machines[id - 1].takenTime = jobHeap.top().time;	//设置占用时间
				doJob(id, machines[id - 1].jobID,0);	//调用处理作业函数
				machines[id - 1].avail = machineHeap.top().avail + jobHeap.top().time;	//设置可用时刻

				//更新最短调度时间
				if (machines[id - 1].avail > shortestTime)
				{
					shortestTime = machines[id - 1].avail;
				}

				machineHeap.pop();	//删除堆顶机器
				machineHeap.push(machines[id - 1]);	//重新插入
				jobHeap.pop();	//删除堆顶作业
				idleCount--;	//空闲机器数减 1
			}
		}
		break;
	}
	}
	CDialogEx::OnTimer(nIDEvent);
}

//增加机器按钮处理函数
void CMachineScheduleDlg::OnBnClickedMAdd()
{
	//处理任务时禁用增加机器操作
	if (!finished) 
	{
		MessageBox("处理任务中，请等待任务处理完成或点击“复位”", "机器调度系统");
	}
	else
	{
		if (mCount < 10)
		{
			machines[mCount].ID = mCount + 1;
			mCount++;
			idleCount++;
			UpdateData(FALSE);
			addMachine(mCount);	//调用增加机器函数
			doJob(mCount,0,1);	//调用处理作业函数
		}
	}
}

//移除机器按钮处理函数
void CMachineScheduleDlg::OnBnClickedMDel()
{
	//处理任务时禁用移除机器操作
	if (!finished)
	{
		MessageBox("处理任务中，请等待任务处理完成或点击“复位”", "机器调度系统");
	}
	else
	{
		if (mCount > 0) {
			machines[mCount - 1].ID = 0;
			machines[mCount - 1].jobID = 0;
			machines[mCount - 1].avail = 0;
			delMachine(mCount);	//调用移除机器函数
			mCount--;
			idleCount--;
			UpdateData(FALSE);
			Invalidate();
		}
	}
}

//增加作业按钮处理函数
void CMachineScheduleDlg::OnBnClickedJAdd()
{
	//处理任务时禁用增加作业操作
	if (!finished)
	{
		MessageBox("处理任务中，请等待任务处理完成或点击“复位”", "机器调度系统");
	}
	else if (GetDlgItemInt(IDC_J_TIME) == 0)
	{
		MessageBox("所需处理时间不能为0！", "机器调度系统");
	}
	else
	{
		if (jCount < 10) {
			jobs[jCount].ID = jCount + 1;
			jobs[jCount].time = GetDlgItemInt(IDC_J_TIME);
			jCount++;
			UpdateData(FALSE);
			addJob(jCount);	//调用增加作业函数
		}
	}
}

//移除作业按钮处理函数
void CMachineScheduleDlg::OnBnClickedJDel()
{
	//处理任务时禁用移除作业操作
	if (!finished)
	{
		MessageBox("处理任务中，请等待任务处理完成或点击“复位”", "机器调度系统");
	}
	else
	{
		if (jCount > 0)
		{
			jobs[jCount - 1].ID = 0;
			jobs[jCount - 1].time = 0;
			delJob(jCount);	//调用移除作业函数
			jCount--;
			UpdateData(FALSE);
		}
	}
}
 
//启动按钮处理函数
void CMachineScheduleDlg::OnBnClickedStart()
{
	//处理任务时禁用启动操作
	if (!finished)
	{
		MessageBox("处理任务中，请等待任务处理完成或点击“复位”", "机器调度系统");
	}
	else if (mCount == 0)
	{
		MessageBox("请添加机器！", "机器调度系统");
	}
	else if (jCount == 0)
	{
		MessageBox("请添加作业！", "机器调度系统");
	}
	else
	{
		finished = false;	//设置任务完成状态为“未完成”

		//处理任务时禁用调速单选按钮
		((CButton*)GetDlgItem(IDC_SLOW))->EnableWindow(FALSE);
		((CButton*)GetDlgItem(IDC_FAST))->EnableWindow(FALSE);
		((CButton*)GetDlgItem(IDC_FASTEST))->EnableWindow(FALSE);

		//将作业、机器数组元素插入到大根堆、小根堆中
		for (int i = 0; i < jCount; i++) {
			jobHeap.push(jobs[i]);
		}
		for (int i = 0; i < mCount; i++) {
			machineHeap.push(machines[i]);
		}

		//将最短调度时间初始化为堆顶作业的处理时间
		shortestTime = jobHeap.top().time;

		//若机器数大于等于作业数，则为每个作业分配一台机器
		//
		//若机器数小于作业数且作业堆不为空，则将堆顶作业分配给堆顶机器
		//将堆顶机器的可用时刻加上堆顶作业的处理时间后重新插入机器堆中
		if (mCount >= jCount) {
			for (int i = 0; i < jCount; i++) {
				machines[i].jobID = i + 1;	//分配作业
				machines[i].takenTime = jobs[i].time;	//设置占用时间
				doJob(i + 1, machines[i].jobID,0);	//调用处理作业函数
				jobHeap.pop();	//删除堆顶作业
				idleCount--;	//空闲机器数减 1
			}
		}
		else {
			while (idleCount >= 1 && !jobHeap.empty()) {
				int id = machineHeap.top().ID;
				machines[id - 1].jobID = jobHeap.top().ID;	//分配作业
				machines[id - 1].takenTime = jobHeap.top().time;	//设置占用时间
				doJob(id, machines[id - 1].jobID,0);	//调用处理作业函数
				machines[id - 1].avail = machineHeap.top().avail + jobHeap.top().time;	//设置可用时刻

				//更新最短调度时间
				if (machines[id - 1].avail > shortestTime)
				{
					shortestTime = machines[id - 1].avail;
				}

				machineHeap.pop();	//删除堆顶机器
				machineHeap.push(machines[id - 1]);	//重新插入
				jobHeap.pop();	//删除堆顶作业
				idleCount--;	//空闲机器数减 1
			}
		}
		SetTimer(1, interval, NULL);	//创建计时器
	}
}

//复位按钮处理函数
void CMachineScheduleDlg::OnBnClickedReset()
{
	KillTimer(1);	//销毁计时器
	for (int i = 0; i < mCount; i++) {
		doJob(i + 1, 0,1);	//调用处理作业函数重置机器、作业状态
		delMachine(i+1);	//调用移除机器函数
		machines[i].ID = 0;		//重置机器数组
		machines[i].avail = 0;	//
	}
	for (int i = 0; i < jCount; i++) {
		delJob(i+1);	//调用移除作业函数
		jobs[i].ID = 0;		//重置作业数组
		jobs[i].time = 0;	//
	}
	mCount = 0;	//重置机器数
	idleCount = 0;	//重置空闲机器数
	jCount = 0;	//重置作业数
	UpdateData(FALSE);
	SetDlgItemText(IDC_J_TIME, "");	//清空作业处理时间编辑框
	machineHeap.reset();	//重置大根堆、小根堆
	jobHeap.reset();		//
	finished = true;	//设置任务完成状态为“完成”

	//复位时启用调速单选按钮
	((CButton*)GetDlgItem(IDC_SLOW))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_FAST))->EnableWindow(TRUE);
	((CButton*)GetDlgItem(IDC_FASTEST))->EnableWindow(TRUE);

	Invalidate();
}

//调速单选按钮处理函数
//通过改变计时器时间间隔来调速
void CMachineScheduleDlg::OnBnClickedSlow()
{
	interval = 1000;
}
void CMachineScheduleDlg::OnBnClickedFast()
{
	interval = 100;
}
void CMachineScheduleDlg::OnBnClickedFastest()
{
	interval = 10;
}
